接下來,我們將探討如何實作前端與後端之間在 Button 狀態上的溝通。
紅色部分是今天會變動的地方。
當使用者按下前端的 Button 時,我們會執行以下動作:
newButton.onclick = function(e) {
// update state and trigger redraw
rerun({
type: 'click',
id: e.target.id,
value: true,
temp: true,
})
}
這段程式碼會發送一個 POST 請求,將 Button 的相關資訊(ID、狀態等)傳送到後端。其中,temp 屬性用來標記這個事件是否為暫時的。
對應到後端,我們定義了一個 Event 結構來表示前端傳來的事件:
type Event struct {
Type string `json:"type"`
ID string `json:"id"`
Value any `json:"value"`
Temp bool `json:"temp"` // for button temperal click
}
這個結構包含了事件類型、Button ID、值以及是否為暫時性點擊等資訊。
在 Endpoint 的處理邏輯中,我們會在執行腳本前後做以下處理:
if event.Type != "" {
state.Set(event.ID, event.Value)
}
rootContainer := NewContainer("root")
f(rootContainer, state)
if event.Type != "" && event.Temp {
state.Del(event.ID)
}
為了讓 Button Component 能根據後端傳來的狀態來顯示不同的樣式,我們需要將 state 作為參數傳入:
func Button(state *tgstate.State, c *Container, label string) bool {
btn := newButton(label)
c.Comps = append(c.Comps, btn)
return state.GetBool(btn.ID)
}
// Return stored state
這個函式會根據 state 中儲存的 Button 狀態來決定是否顯示按鈕的按下效果。
以下是一個簡單的測試範例,展示了如何使用 Button Component:
if tg.Button(state, root, "hello") {
tg.Text(root, "hello!")
}